#include "glwidget.h"

GLfloat vertices[] = {
    0.5f, 0.5f, 0.0f,   // 右上角
    0.5f, -0.5f, 0.0f,  // 右下角
    -0.5f, -0.5f, 0.0f, // 左下角
    -0.5f, 0.5f, 0.0f   // 左上角
};

unsigned int indices[] = {
    // 注意索引从0开始!
    // 此例的索引(0,1,2,3)就是顶点数组vertices的下标，
    // 这样可以由下标代表顶点组合成矩形

    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};

GLWidget::GLWidget(QWidget* parent):
    QOpenGLWidget(parent),
    QOpenGLFunctions_4_5_Core()
{

}

void GLWidget::initializeGL()
{
    // 初始化 gl 函数
    this->initializeOpenGLFunctions();

    // 创建缓冲区
    PreCreateBuffers();

    // 编译着色器
    PreCompileShaders();
}

void GLWidget::resizeGL(int w, int h)
{

}

void GLWidget::paintGL()
{
    // 清除绘制缓冲区
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // 绑定 VAO
    glBindVertexArray(VAO);
    // 绘制
    // // 绘制模式 -> 线框
    // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    // 绘制模式 -> 填充
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    // 解绑 VAO
    glBindVertexArray(0);
}

void GLWidget::PreCreateBuffers()
{
    // 生成 顶点数组对象
    glGenVertexArrays(1, &VAO);
    // 绑定VAO
    glBindVertexArray(VAO);

    // ------------------ 顶点缓冲区 ------------------
    // 生成 顶点缓冲区
    glGenBuffers(1, &VBO);
    // 绑定 顶点缓冲区 -> 在绑定缓冲区之后，后面所做的关于缓冲区的配置都是关于绑定的缓冲区的
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // 配置缓冲区数据 -> 将指定的数据复制到目标缓冲区中
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    // 配置顶点属性 -> 解析顶点缓冲区数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
    // 启用顶点属性
    glEnableVertexAttribArray(0);
    // ------------------------------------

    // ------------------ 索引缓冲区 ------------------
    // 生成 索引缓冲区
    glGenBuffers(1, &EBO);
    // 绑定 索引缓冲区
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    // 配置缓冲区数据
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    // ------------------------------------

    // 解绑 VAO
    glBindVertexArray(0);
}

void GLWidget::PreCompileShaders()
{
    pShaderProgram = std::make_unique<QOpenGLShaderProgram>();
    // 创建 顶点着色器对象
    pShaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/sample_vs.vert");

    // 创建 像素着色器对象
    pShaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/sample_fs.frag");

    // 编译链接
    pShaderProgram->link();
}
